home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 101 (1989-08-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 101 (1989-08-15)(Ossowski, Stefan)(DE)(PD).adf / Puzzle / Puzzle.c < prev    next >
C/C++ Source or Header  |  1989-04-20  |  8KB  |  424 lines

  1. /*
  2.  * Puzzle
  3.  * ~~~~~~
  4.  * Copyright © 1989  Oo
  5.  * by            o.·°
  6.  * Walter Dörwald ·°·o·.o
  7.  *              O
  8.  */
  9.  
  10. #include <exec/types.h>
  11. #include <intuition/intuition.h>
  12. #include <graphics/rastport.h>
  13. #include <proto/dos.h>
  14.  
  15.  
  16. /* Monitor als Zufallsgenerator! */
  17. #define RNDREG ((UBYTE *)0xDFF007)
  18. #define rand1() ((*RNDREG)&112)
  19. #define rand2() (((*RNDREG)&6)>>1)
  20.  
  21. /* Auch für die, die tatsächlich     */
  22. /* noch die Workbenchfarben benutzen */
  23. #ifndef ORG
  24. #define DUNK 0
  25. #else
  26. #define DUNK 2
  27. #endif
  28.  
  29. /* Menü-returns */
  30. #define G_NIX 0
  31. #define G_END 1
  32. #define G_OK  2
  33.  
  34. /* Grafik, wird automatisch ins ChipMem geladen */
  35. extern UWORD Tile_Data[];
  36. extern UWORD Pic_Data[];
  37.  
  38. struct TextAttr TA_NORM =
  39. {
  40.    (UBYTE *)"topaz.font",TOPAZ_EIGHTY,FSF_BOLD,FPF_ROMFONT
  41. };
  42.  
  43. struct Image Tile =
  44. {
  45.    11,14,32,16,2,NULL,0x3,0x0,NULL
  46. };
  47.  
  48. struct Image Pic =
  49. {
  50.    5,11,148,74,2,Pic_Data,0x3,0x0,NULL
  51. };
  52.  
  53. struct Gadget Start =
  54. {
  55.    NULL,95,71,43,9,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,NULL,0L,NULL,2,NULL
  56. };
  57.  
  58. struct Gadget OK =
  59. {
  60.    &Start,20,71,43,9,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,NULL,0L,NULL,1,NULL
  61. };
  62.  
  63. struct NewWindow NewPuzzleWin =
  64. {
  65.    300,100,158,98,DUNK,1,MOUSEBUTTONS|CLOSEWINDOW,
  66.    RMBTRAP|ACTIVATE|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE,
  67.    NULL,NULL,(UBYTE *)" Puzzle ",NULL,NULL,0,0,0,0,WBENCHSCREEN
  68. };
  69.  
  70. struct Window *PuzzleWin;
  71. struct RastPort *RP;
  72. UWORD Count;
  73.  
  74. UBYTE *Zaehl = "Züge: ·····";
  75. #define LEN 11L
  76.  
  77.  
  78. UBYTE Brett[] =
  79. {
  80.    01,02,03,04,
  81.    05,06,07,08,
  82.    09,10,11,12,
  83.    13,14,15,00
  84. };
  85.  
  86. UBYTE Fill[] =
  87. {
  88.    00,01,02,03,07,11,15,14,13,12,08,04,05,06,10,09,
  89.    09,10,06,05,04,08,12,13,14,15,11,07,03,02,01,00,
  90.    00,15,01,14,02,13,03,12,07,08,11,04,10,05,09,06,
  91.    06,09,05,10,04,11,08,07,12,03,13,02,14,01,15,00,
  92.    01,00,04,05,09,08,12,13,14,15,11,10,06,07,03,02,
  93.    00,03,15,12,01,07,14,08,02,11,13,04,05,06,10,09,
  94.    00,07,14,05,12,03,10,01,08,15,06,13,04,11,02,09,
  95.    00,02,05,07,08,10,13,15,01,03,04,06,09,11,12,14
  96. };
  97.  
  98.  
  99. /* Brauch ma niat */
  100. void MemCleanup(){}
  101.  
  102.  
  103. /* Libraries */
  104. #define INTUITION_LIB 0L
  105. #define GRAPHICS_LIB 0L
  106. #include "IN.lib().c"
  107.  
  108.  
  109. /* Deklarationen */
  110. UBYTE Fertig(void);
  111. UBYTE Schieb(UBYTE);
  112. void Set(UBYTE,UBYTE);
  113. void SetBrett(void);
  114. void Zug(UWORD);
  115. UBYTE Menu(UBYTE);
  116. void Mix(void);
  117. void _main(void);
  118.  
  119. void _main()
  120.  
  121. {
  122.     register struct IntuiMessage *IMess;
  123.     ULONG MessClass;
  124.     UWORD Code;
  125.     register UBYTE X,
  126.            Y,
  127.            ready = FALSE;
  128.  
  129.  
  130.    /* Bib's auf */
  131.    OpenLib();
  132.  
  133.    /* Steine mixen */
  134.    Mix();
  135.  
  136.    if (PuzzleWin = OpenWindow(&NewPuzzleWin))
  137.    {
  138.       /* RastPort für schnellen Zugriff */
  139.       RP = PuzzleWin->RPort;
  140.       /* Und jetzt die ganze Grafik vorbereiten */
  141.       SetFont(RP,OpenFont(&TA_NORM));
  142.       SetAPen(RP,1);
  143.       RectFill(RP,5,11,152,94);
  144.       SetAPen(RP,3);
  145.       RectFill(RP,5,11,152,11);
  146.       RectFill(RP,5,11,7,94);
  147.       SetAPen(RP,DUNK);
  148.       SetBPen(RP,1);
  149.       /* Züge setzen und ausgeben */
  150.       Zug(Count = 0);
  151.       /* Brett zeichnen */
  152.       SetBrett();
  153.  
  154.       do
  155.       {
  156.      /* Warten auf Nachricht */
  157.      WaitPort(PuzzleWin->UserPort);
  158.      while (IMess = (struct IntuiMessage *)GetMsg(PuzzleWin->UserPort))
  159.      {
  160.         /* Wichtigstes merken; Nachricht beantworten */
  161.         MessClass = IMess->Class;
  162.         Code = IMess->Code;
  163.         X = (UBYTE)IMess->MouseX;
  164.         Y = (UBYTE)IMess->MouseY;
  165.         ReplyMsg((struct Message *)IMess);
  166.  
  167.         /* Verschieben */
  168.         if (MessClass == MOUSEBUTTONS)
  169.         {
  170.            switch(Code)
  171.            {
  172.           case SELECTDOWN:
  173.              /* Test ob innerhalb Grenzen */
  174.              if (X>=12 && X<=150 && Y>=14 && Y<=80)
  175.              {
  176.             X -= 12;
  177.             Y -= 14;
  178.             if ((X % 36)<26 && (Y % 18)<14)
  179.             {
  180.                X /= 36;
  181.                Y /= 18;
  182.                /* Verschieben und mitzählen */
  183.                if (Schieb((UBYTE)(X+(Y<<2))))
  184.                {
  185.                   Zug(++Count);
  186.                   if (Fertig())
  187.                  ready = Menu(TRUE);
  188.                }
  189.             }
  190.              }
  191.              break;
  192.           case MENUDOWN:
  193.              ready = Menu(FALSE);
  194.            }
  195.         }
  196.      }
  197.       } while (MessClass != CLOSEWINDOW && ready != G_END);
  198.  
  199.       /* Fenster zu */
  200.       CloseWindow(PuzzleWin);
  201.    }
  202.  
  203.    /* Bib's zu */
  204.    CloseLib();
  205.  
  206.    /* Das war's */
  207. }
  208.  
  209.  
  210. void Set(Pos,Num)
  211.  
  212. register UBYTE Pos,
  213.            Num;
  214.  
  215. {
  216.    /* Imagezeiger neu setzen */
  217.    /* Grafik benötigt 128 Bytes (Shift 6, da UWORD) */
  218.    Tile.ImageData = Tile_Data + (ULONG)(Num<<6);
  219.    /* Zeichnen (Offset steht in ImageStruktur) */
  220.    DrawImage(RP,&Tile,(Pos&3)*36,(Pos>>2)*18);
  221. }
  222.  
  223. UBYTE Schieb(Pos)
  224.  
  225. register UBYTE Pos;
  226.  
  227. {
  228.    /* Pos nicht oben und oben leer ? */
  229.    if ((Pos>3) && (!Brett[Pos-4]))
  230.       Set((UBYTE)(Pos-4),Brett[Pos-4] = Brett[Pos]);
  231.    /* Pos nicht rechts und rechts leer ? */
  232.    else if (((Pos&3)<3) && (!Brett[Pos+1]))
  233.       Set((UBYTE)(Pos+1),Brett[Pos+1] = Brett[Pos]);
  234.    /* Pos nicht unten und unten leer ? */
  235.    else if ((Pos<12) && (!Brett[Pos+4]))
  236.       Set((UBYTE)(Pos+4),Brett[Pos+4] = Brett[Pos]);
  237.    /* Pos nicht links und links leer ? */
  238.    else if ((Pos&3) && (!Brett[Pos-1]))
  239.       Set((UBYTE)(Pos-1),Brett[Pos-1] = Brett[Pos]);
  240.    /* dann hald niat */
  241.    else
  242.       return(FALSE);
  243.  
  244.    /* Leeres Feld neu zeichen */
  245.    Set(Pos,Brett[Pos] = 0);
  246.    return(TRUE);
  247. }
  248.  
  249.  
  250. UBYTE Fertig()
  251.  
  252. {
  253.    register UBYTE i;
  254.  
  255.    /* Alle Felder testen */
  256.    for (i = 0;i<16;i++)
  257.    {
  258.       /* Liegt Stein falsch ? */
  259.       if (Brett[i] != ((i+1)&15))
  260.      return(FALSE);
  261.    }
  262.    return(TRUE);
  263. }
  264.  
  265. void SetBrett()
  266.  
  267. {
  268.    register UBYTE  i,
  269.            j,
  270.           *FillPtr;
  271.  
  272.    /* Grafik wiederherstellen */
  273.    SetAPen(RP,1);
  274.    RectFill(RP,8,12,152,84);
  275.    SetAPen(RP,3);
  276.    RectFill(RP,5,11,152,11);
  277.    RectFill(RP,5,11,7,94);
  278.    SetAPen(RP,DUNK);
  279.    /* Setzmodus per Zufall */
  280.    FillPtr = Fill + rand1();
  281.  
  282.    /* Leere Felder malen */
  283.    for (i = 0;i<16;i++)
  284.    {
  285.       j = FillPtr[i];
  286.       RectFill(RP,9+((j&3)*36),13+((j>>2)*18),40+((j&3)*36),28+((j>>2)*18));
  287.       Set(j,0);
  288.       Delay(3);
  289.    }
  290.    /* Steine setzen */
  291.    for (--i;i != 0xFF;i--)
  292.    {
  293.       j = FillPtr[i];
  294.       Set(j,Brett[j]);
  295.       Delay(3);
  296.    }
  297. }
  298.  
  299.  
  300.  
  301. UBYTE Menu(flag)
  302.  
  303. UBYTE flag;
  304.  
  305. {
  306.    register struct IntuiMessage *IMess;
  307.    register ULONG MessClass;
  308.    register UWORD ID;
  309.    register UBYTE ret = G_NIX;
  310.  
  311.    /* Grafik zeichnen */
  312.    DrawImage(RP,&Pic,0,0);
  313.    /* Gadget verwursten */
  314.    if (flag)
  315.       OK.Flags |= GADGDISABLED;
  316.    else
  317.       OK.Flags &= (!GADGDISABLED);
  318.    /* Gadgets ein */
  319.    AddGList(PuzzleWin,&OK,-1,2,NULL);
  320.    RefreshGList(&OK,PuzzleWin,NULL,2);
  321.    /* Und jetzt auf Gadgets warten */
  322.    ModifyIDCMP(PuzzleWin,GADGETUP|CLOSEWINDOW);
  323.    /* Warten auf Nachricht */
  324.    do
  325.    {
  326.       WaitPort(PuzzleWin->UserPort);
  327.       while (IMess = (struct IntuiMessage *)GetMsg(PuzzleWin->UserPort))
  328.       {
  329.      /* Wichtigstes merken; Nachricht beantworten */
  330.      MessClass = IMess->Class;
  331.      ID = ((struct Gadget *)(IMess->IAddress))->GadgetID;
  332.      ReplyMsg((struct Message *)IMess);
  333.  
  334.      /* SchließGadget ? */
  335.      if (MessClass == CLOSEWINDOW)
  336.         ret = G_END;
  337.      /* Oder OK bzw. Start ? */
  338.      else
  339.         ret = G_OK;
  340.       }
  341.    } while (!ret);
  342.    /* Gadgets aus */
  343.    ModifyIDCMP(PuzzleWin,MOUSEBUTTONS|CLOSEWINDOW);
  344.    RemoveGList(PuzzleWin,&OK,2);
  345.    /* Start, dann mixen */
  346.    if ((ret == G_OK) && (ID == 2))
  347.    {
  348.       Zug(Count = 0);
  349.       Mix();
  350.    }
  351.    /* Steine wieder setzen */
  352.    if (ret != G_END)
  353.       SetBrett();
  354.    return (ret);
  355. }
  356.  
  357. void Zug(Count)
  358.  
  359. register UWORD Count;
  360.  
  361. {
  362.    register UBYTE *i;
  363.  
  364.    /* Alle Zeichen durch */
  365.    for (i = Zaehl+10;i>Zaehl+5;i--)
  366.    {
  367.       /* Ziffer setzen */
  368.       *i = '0' + (UBYTE)(Count % 10);
  369.       /* Count/10 für nächste Abfrage und testen */
  370.       Count /= 10;
  371.    }
  372.    /* Ausgeben */
  373.    Move(RP,37,92);
  374.    Text(RP,Zaehl,LEN);
  375. }
  376.  
  377. void Mix()
  378.  
  379. {
  380.    register UWORD i;
  381.    register UBYTE Pos;
  382.  
  383.    /* Leeres Feld finden */
  384.    for (Pos = 0;Pos<16;Pos++)
  385.       if (!Brett[Pos])
  386.      break;
  387.  
  388.    /* Mixen, 1500× dürfte reichen (und geht auch noch schnell) */
  389.    for (i = 0;i<1500;i++)
  390.    {
  391.       switch (rand2())
  392.       {
  393.      case 0: /* Oben */
  394.         if (Pos>3)
  395.         {
  396.            Brett[Pos] = Brett[Pos -= 4];
  397.            Brett[Pos] = 0;
  398.            break;
  399.         }
  400.      case 1: /* Rechts */
  401.         if ((Pos&3) < 3)
  402.         {
  403.            Brett[Pos] = Brett[++Pos];
  404.            Brett[Pos] = 0;
  405.            break;
  406.         }
  407.      case 2: /* Unten */
  408.         if (Pos<12)
  409.         {
  410.            Brett[Pos] = Brett[Pos += 4];
  411.            Brett[Pos] = 0;
  412.            break;
  413.         }
  414.      case 3: /* Links */
  415.         if (Pos&3)
  416.         {
  417.            Brett[Pos] = Brett[--Pos];
  418.            Brett[Pos] = 0;
  419.         }
  420.         break;
  421.       }
  422.    }
  423. }
  424.